/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.worldscale.xp.wslib.im.jabber.impl;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import net.worldscale.xp.wslib.im.jabber.JabberID;
import net.worldscale.xp.wslib.im.jabber.JabberRosterModel;
import net.worldscale.xp.wslib.wsxml.DomUtil;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 * @author Kun
 */
final class ImplRosterModel extends JabberRosterModel {

	private final Hashtable<JabberID, MyContact> mContacts;
	private final Hashtable<String, MyContactGroup> mGroups;

	public ImplRosterModel() {
		mContacts = new Hashtable<JabberID, MyContact>();
		mGroups = new Hashtable<String, MyContactGroup>();
		mGroups.put("", new MyContactGroup(""));
	}

	@Override
	public Contact getContact(JabberID jid) {
		return this.mContacts.get(jid);
	}

	@Override
	public Contact[] getContactsInGroup(String groupName) {
		final ContactGroup group = this.getGroup(groupName);
		if (group == null) {
			return new Contact[0];
		}
		final Vector<Contact> v = new Vector<Contact>();
		final JabberID[] ids = group.getContactIDs();
		for (int i = 0; i < ids.length; i++) {
			final Contact contact = this.getContact(ids[i]);
			if (contact != null) {
				v.addElement(contact);
			}
		}
		final Contact[] array = new Contact[v.size()];
		v.copyInto(array);
		return array;
	}

	@Override
	public ContactGroup getGroup(String groupName) {
		if (groupName == null) {
			groupName = "";
		}
		return this.mGroups.get(groupName);
	}

	@Override
	public Contact[] getContacts() {
		final Vector<Contact> v = new Vector<Contact>();
		final Enumeration<MyContact> enu = this.mContacts.elements();
		for (; enu.hasMoreElements();) {
			v.addElement(enu.nextElement());
		}
		final Contact[] array = new Contact[v.size()];
		v.copyInto(array);
		return array;
	}

	@Override
	public ContactGroup[] getGroups() {
		final Vector<MyContactGroup> v = new Vector<MyContactGroup>();
		Enumeration<MyContactGroup> enu = this.mGroups.elements();
		for (; enu.hasMoreElements();) {
			v.addElement(enu.nextElement());
		}
		ContactGroup[] array = new ContactGroup[v.size()];
		v.copyInto(array);
		return array;
	}

	@Override
	public Element getRoster() {
		return null;
	}

	private void processRosterItem(Element item) {
		final String jid, name, subscription;
		jid = item.getAttribute("jid");
		name = item.getAttribute("name");
		subscription = item.getAttribute("subscription");
		final MyContact contact = new MyContact(jid);
		contact.mName = name;
		contact.mSubscription = subscription;
		final NodeList nl = item.getChildNodes();
		for (int i = nl.getLength() - 1; i >= 0; i--) {
			final Node child = nl.item(i);
			if (child instanceof Element) {
				final Element ele = (Element) child;
				if ("group".equals(ele.getTagName())) {
					final String group = DomUtil.getTextContent(ele);
					contact.addGroup(group);
				}
			}
		}
		addContact(contact);
	}

	private void addContact(MyContact contact) {
		if (contact != null) {
			this.mContacts.put(contact.getJID().getPureJID(), contact);
			final String[] gs = contact.getOwnerGroupNames();
			for (int i = gs.length - 1; i >= 0; i--) {
				final String gname = gs[i];
				this.getGroup(gname, true).addContact(contact);
			}
			this.getGroup("", true).addContact(contact);
			System.out.println(contact);
		}
	}

	@Override
	public void setRoster(Element roster) {
		if (roster == null) {
			return;
		}
		if (!"query".equals(roster.getTagName())) {
			return;
		}
		if (!"jabber:iq:roster".equals(roster.getAttribute("xmlns"))) {
			return;
		}
		final NodeList nl = roster.getChildNodes();
		final int len = nl.getLength();
		for (int i = 0; i < len; i++) {
			final Node node = nl.item(i);
			if (node instanceof Element) {
				final Element item = (Element) node;
				if ("item".equals(item.getTagName())) {
					this.processRosterItem(item);
				}
			}
		}
	}

	private static final class MyContactGroup extends ContactGroup {

		private final String mName;
		private final Vector<JabberID> mContactIDs;
		private boolean mIsOpen = true;

		public MyContactGroup(String name) {
			mName = name;
			mContactIDs = new Vector<JabberID>();
		}

		public void addContact(MyContact contact) {
			this.mContactIDs.addElement(contact.getJID().getPureJID());
		}

		@Override
		public String getName() {
			return mName;
		}

		@Override
		public void setOpen(boolean isOpen) {
			mIsOpen = isOpen;
		}

		@Override
		public boolean isOpen() {
			return this.mIsOpen;
		}

		@Override
		public JabberID[] getContactIDs() {
			final JabberID[] array = new JabberID[this.mContactIDs.size()];
			this.mContactIDs.copyInto(array);
			return array;
		}
	}

	private MyContactGroup getGroup(String name, boolean create) {
		MyContactGroup g = this.mGroups.get(name);
		if ((g == null) && (create)) {
			g = new MyContactGroup(name);
			this.mGroups.put(name, g);
		}
		return g;
	}

	private final class MyContact extends Contact {

		private JabberID mJID;
		private String mName;
		private String mSubscription;
		private final Vector<String> mResources = new Vector<String>();
		private final Vector<String> mGroups = new Vector<String>();

		public MyContact(String jid) {
			JabberID jidobj = new JabberID(jid);
			mJID = jidobj.getPureJID();
			final String res = jidobj.getResource();
			if (res != null) {
				if (res.length() > 0) {
					this.addResource(res);
				}
			}
		}

		public void addResource(String res) {
			System.out.println("resource=" + res);
			this.mGroups.addElement(res);
		}

		public void addGroup(String group) {
			System.out.println("group=" + group);
			this.mGroups.addElement(group);
		}

		@Override
		public String[] getResources() {
			final Vector v = this.mResources;
			final String[] array = new String[v.size()];
			v.copyInto(array);
			return array;
		}

		@Override
		public String[] getOwnerGroupNames() {
			final Vector v = this.mGroups;
			final String[] array = new String[v.size()];
			v.copyInto(array);
			return array;
		}

		@Override
		public JabberID getJID() {
			return mJID;
		}

		@Override
		public String getName() {
			return this.mName;
		}

		@Override
		public String getSubscription() {
			return this.mSubscription;
		}

		@Override
		public String toString() {
			return "JabberContact[" + this.mJID + "|" + this.mName + "|"
					+ this.mSubscription + "]";
		}
	}
}
